package it.okkam.geosparql;

import it.okkam.strutturedati.Extent;
import it.okkam.strutturedati.ExtentCcc;
import it.okkam.strutturedati.GeometryCcc;
import it.okkam.strutturedati.Punto;
import it.okkam.utility.ExtentComuni;
import it.okkam.utility.UtilityQuery;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.tdb.TDBFactory;

public class GeoGetExtentParticelleCandidate {
	
	public static HashMap<String, Dataset> dataSetComuni = new HashMap<String, Dataset>();

	
	
	
public HashMap<String,List<ExtentCcc>> getParticelleCandidate (HashMap<String, HashMap<String , List<Extent>>>  cambiamentoParticelleCandidate) {
	HashMap<String,List<ExtentCcc>> hmListaExtCccOk = new HashMap<String, List<ExtentCcc>>();
	GeoGetExtentParticelleCandidate geo = new GeoGetExtentParticelleCandidate();
	UtilityQuery utq = new UtilityQuery();
	String grafoCambiamenti = "http://www.okkam.org/provinciale/cambiamenti";
	Dataset dsProvinciale = TDBFactory.assembleDataset("/home/okkam/Nicola/assemblers/provinciale-assembler.ttl");
	Model modelCambiamenti = dsProvinciale.getNamedModel(grafoCambiamenti);	
	
	Iterator iter = cambiamentoParticelleCandidate.keySet().iterator();
	while (iter.hasNext()){
		String idCambiamento = (String)iter.next();
		HashMap<String , List<Extent>> hmExtentParticelleCandidate = cambiamentoParticelleCandidate.get(idCambiamento);
		Geometry geometriaCambiamento = geo.getGeometriaCambiamento(idCambiamento, modelCambiamenti);
		List<ExtentCcc> listaExtCCCParticelleCandidate = geo.getExtentsParticelleCandidate(idCambiamento, cambiamentoParticelleCandidate);
		List<GeometryCcc> listaGeomCCCParticelleCandidate = geo.getGeometrieParticelleCandidate(listaExtCCCParticelleCandidate);
	
		Iterator<GeometryCcc> iterList = listaGeomCCCParticelleCandidate.iterator();
		List<ExtentCcc> listaExtCccOk = new ArrayList<ExtentCcc>();
		while (iterList.hasNext()){
			GeometryCcc geometriaCccParticella = iterList.next();
			ExtentCcc extCccParticellaOk = geo.intersect(geometriaCccParticella, geometriaCambiamento);
			if (extCccParticellaOk!=null){
				listaExtCccOk.add(extCccParticellaOk);}
		}
		hmListaExtCccOk.put(idCambiamento, listaExtCccOk);
		
	}
	
	
	
	
	return hmListaExtCccOk;
}
	/**
	 * Questo metodo prende in ingresso il l-hm dei cambiamenti con la lista degli extent per ogni comune e restituisce la lista Extent delle particelle candidate
	 *
	 * @param  String  id del cambiamento
	 * @param  HashMap<String, HashMap<String , List<Extent>>> hm con id + hm con comune e lista extent delle particelle del comune
	 * 
	 * @return      lista Extent delle particelle candidate
	 */


	@SuppressWarnings("rawtypes")
	private List<ExtentCcc> getExtentsParticelleCandidate (String id , HashMap<String, HashMap<String , List<Extent>>>  cambiamentoParticelleCandidate ){
		UtilityQuery utq = new UtilityQuery();
		Iterator keyIter = cambiamentoParticelleCandidate.keySet().iterator();
		HashMap<String, List<Extent>> extents = new HashMap<String, List<Extent>>();
		List<ExtentCcc> lista = new ArrayList<ExtentCcc>();
		while (keyIter.hasNext()){
			String element = (String)keyIter.next();
			if (element.equals(id)){
				HashMap<String , List<Extent>> hm = cambiamentoParticelleCandidate.get(element);
				Iterator iter = hm.keySet().iterator();
				while (iter.hasNext()){
					String comune =(String)iter.next();
					List<Extent> listaExtent = hm.get(comune);
					Iterator<Extent> it = listaExtent.iterator();
					while (it.hasNext()){
						Extent ext = it.next();
						ExtentCcc extC = new ExtentCcc();
						extC.setCcc(comune);
						extC.setExt(ext);
						lista.add(extC);
					}
				}
			}
		}
		return lista ;}
	
	
	
	/**
	 * Questo metodo prende in ingresso la lista degli extent e restituisce la lista delle geometrie 
	 *
	 * @param  List<Extent>  Lista Extent
	 * 
	 * @return      lista geometrie delle particelle candidate
	 */


	@SuppressWarnings("rawtypes")
	private List<GeometryCcc> getGeometrieParticelleCandidate ( List<ExtentCcc> listaExtent ){
		UtilityQuery utq = new UtilityQuery();
		Geometry geometria = null;
		List<GeometryCcc> lista = new ArrayList<GeometryCcc>();
		Iterator iter = listaExtent.iterator();
		while (iter.hasNext()){
			ExtentCcc ext = (ExtentCcc)iter.next();
			Extent extent = ext.getExt();
			String extentString = utq.getGeometryExtentString(ext);
			String ccc = ext.getCcc();
			try {
				geometria  = new WKTReader().read(extentString);
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			GeometryCcc geoCcc = new GeometryCcc();
			geoCcc.setCcc(ccc);
			geoCcc.setExt(extent);
			geoCcc.setGeo(geometria);
		lista.add(geoCcc);	
		}
		
		return lista ;}

	/**
	 * Questo metodo restituisce 

	 *
	 * @param  
	 * @param  
	 * @return 
	 */

 
	public Geometry getGeometriaCambiamento(String id, Model model){
		UtilityQuery utq = new UtilityQuery();
		GeoStringQuery geos = new GeoStringQuery();
		String queryString = geos.getQSgetGeometria(id);
		com.hp.hpl.jena.query.Query query = QueryFactory.create(queryString);
		QueryExecution qexec = QueryExecutionFactory.create(query, model);
        ResultSet results = qexec.execSelect();
        List<Punto> punti = new ArrayList<Punto>();
        for (; results.hasNext();) {
        	QuerySolution record = results.next();
        	Punto punto = new Punto();
        	String x = utq.getCoordinata(record.get("lat").toString());//check
        	String y = utq.getCoordinata(record.get("long").toString());// check
        	punto.setX(Double.valueOf(x));
        	punto.setY(Double.valueOf(y));
        	punti.add(punto);  		  
        }
		
		String geoString = utq.getStringGeometryCambiamento(punti);
        Geometry geometria = null;
        try {
			geometria = new WKTReader().read(geoString);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	
		return geometria;
		//return null;
	}
	
	private ExtentCcc intersect (GeometryCcc particella, Geometry geoCambiamento){
		ExtentCcc out = new ExtentCcc();
		Geometry geoParticella = particella.getGeo();
		
		if (geoParticella.intersects(geoCambiamento)){
			out.setExt(particella.getExt());
			out.setCcc(particella.getCcc());
		}
		else{
			out= null;
		}
		return out;
	}
	
	public Polygon getPolyCambiamento(String id, Model model){
		UtilityQuery utq = new UtilityQuery();
		GeoStringQuery geos = new GeoStringQuery();
		String queryString = geos.getQSgetGeometria(id);
		com.hp.hpl.jena.query.Query query = QueryFactory.create(queryString);
		QueryExecution qexec = QueryExecutionFactory.create(query, model);
        ResultSet results = qexec.execSelect();
        List<Punto> punti = new ArrayList<Punto>();
        for (; results.hasNext();) {
        	QuerySolution record = results.next();
        	Punto punto = new Punto();
        	String x = utq.getCoordinata(record.get("lat").toString());//check
        	String y = utq.getCoordinata(record.get("long").toString());// check
        	punto.setX(Double.valueOf(x));
        	punto.setY(Double.valueOf(y));
        	punti.add(punto);  		  
        }
		
        Coordinate[] listacoord= utq.getListCoordPunto(punti);
    	GeometryFactory fact = new GeometryFactory();
    	LinearRing linear = new GeometryFactory().createLinearRing(listacoord);
    	Polygon poly = new Polygon(linear, null, fact);
    	return poly ;        
	
	}
}
